﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using Cost.Models;
using Cost.Services.Services;
using NBlock.Components.ImportExport;
using NBlock.Core;
using NBlock.Core.ORM;
using NBlock.MVCExtensions;

namespace Cost.Controllers
{
    public class MaterialProcessController : Controller
    {
        #region 构造函数
        private readonly ICostRepository<MaterialProcess> materialprocessRepository;
        private readonly ICostRepository<MaterialProcessItem> materialprocessitemRepository;
        private readonly ICostRepository<MaterialProcessPlanView> materialProcessPlanViewRepository;
        private readonly ICostRepository<Material> materialRepository;
        private readonly ICostRepository<Storage> storageRepository;
        private readonly ICostRepository<StockRecord> stockrecordRepository;
        private readonly StorageService storageService;
        private readonly IEnumService enumService;
        private readonly IWordExporter wordExporter;
        private const string ListState = "Draft";
        private const string State = "Draft";
        public MaterialProcessController(ICostRepository<MaterialProcess> materialprocessRepository,
            ICostRepository<MaterialProcessItem> materialprocessitemRepository,
            ICostRepository<MaterialProcessPlanView> materialProcessPlanViewRepository,
            ICostRepository<Storage> storageRepository,
            ICostRepository<StockRecord> stockrecordRepository,
            ICostRepository<Material> materialRepository,
            StorageService storageService,
            IEnumService enumService,
            IWordExporter wordExporter)
        {
            this.materialprocessRepository = materialprocessRepository;
            this.materialprocessitemRepository = materialprocessitemRepository;
            this.materialProcessPlanViewRepository = materialProcessPlanViewRepository;
            this.materialRepository = materialRepository;
            this.storageRepository = storageRepository;
            this.stockrecordRepository = stockrecordRepository;
            this.storageService = storageService;
            this.enumService = enumService;
            this.wordExporter = wordExporter;
        }
        #endregion

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Edit(string Id, DateTime? date, string type)
        {
            var data = materialprocessRepository.Find(Id) ?? new MaterialProcess
            {
                OrderState = "Draft",
                ProcessDate = date ?? DateTime.Today.AddDays(1),
            };

            // 子表数据
            var items = GetItems(Id, date, type);
            ViewBag.MaterialList = items;
            ViewBag.Type = type;
            data.TotalWeight = items.Sum(m => m.ProcessWeight);
            ViewBag.Type = type;
            return View(data);
        }

        private IList<MaterialProcessItem> GetItems(string orderId, DateTime? date, string Type)
        {
            // 从加工计划中产生明细
            if (date.HasValue)
            {
                var list = materialProcessPlanViewRepository.FindAll(p => p.Date == date && p.BigClass == Type)
                   .ToList().Select(p => new MaterialProcessItem
                   {
                       Id = Guid.NewGuid().ToString(),
                       Code = p.Code,
                       Category = p.Category,
                       MaterialId = p.Id,
                       Name = p.Name,
                       PickWeight = Math.Ceiling((p.ProcessWeight.Value / p.ProcessRate.Value) * 10) / 10,
                       ProcessRate = p.ProcessRate.Value,
                       ProcessWeight = p.ProcessWeight.Value,
                       RawMaterialId = p.RawMaterialId,
                       RawMaterialName = p.RawMaterialName,
                       State = "Draft",
                       StorageWeight = p.ProcessWeight.Value, // 默认与加工数量相同
                       BigClass = p.BigClass,
                   }).ToList();

                return list;
            }
            else
            {
                var list = materialprocessitemRepository.FindAll(p => p.OrderId == orderId).ToList();
                return list;
            }
        }

        [HttpPost]
        public JsonResult Save(string Id, IList<MaterialProcessItem> MaterialList)
        {
            var data = materialprocessRepository.Find(Id) ?? new MaterialProcess();
            TryUpdateModel(data);

            // 如果不是草稿，则不能保存只能查看
            if (data.OrderState != "Draft")
            {
                return Json(new nbAjaxMessage
                {
                    IsSuccess = false,
                    Msg = "加工单状态已经不是草稿了，只能查看，不允许保存。"
                });
            }

            var ItemDesc = string.Empty;
            decimal totalWeight = 0;
            // 先删除所有子表，再保持所有子表数据
            materialprocessitemRepository.DeleteAll(m => m.OrderId == data.Id);
            if (MaterialList != null)
            {
                foreach (var m in MaterialList)
                {
                    m.OrderId = Id;
                    m.Date = data.ProcessDate;
                    m.State = State;
                    m.PickWeight = Math.Ceiling((m.ProcessWeight / m.ProcessRate) * 10) / 10;
                    m.StorageWeight = m.ProcessWeight;
                    materialprocessitemRepository.Insert(m);

                    // 计算总重量和品名汇总
                    ItemDesc += m.Name + "，";
                    totalWeight += m.ProcessWeight;
                }

            }
            data.ItemDesc = ItemDesc.Trim('，');
            data.TotalWeight = totalWeight;
            materialprocessRepository.Save(data);

            return Json(nbAjaxMessage.Successful);
        }

        [HttpPost]
        public JsonResult Delete(string Id)
        {
            materialprocessRepository.Delete(Id);
            materialprocessitemRepository.DeleteAll(m => m.OrderId == Id);
            return Json(nbAjaxMessage.Successful);
        }

        [HttpPost]
        public JsonResult List(DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            Expression<Func<MaterialProcess, bool>> filter = null;
            if (date.HasValue)
                filter = m => m.ProcessDate == date;

            var pageData = materialprocessRepository.GetPageable(pager, filter, where);
            var data = pager.ToGridData(pageData);
            return Json(data);
        }

        #region 领料
        public ActionResult Picking(string Id)
        {
            var data = materialprocessRepository.Find(Id);
            if (data.OrderState != "Draft")
            {
                throw new Exception(string.Format("当前加工单（{0}）的状态不是草稿，所以无法领料！", Id));
            }

            // 子表数据
            var items = GetPickingItems(Id);
            ViewBag.detail = items;

            return View(data);
        }

        public IList<MaterialProcessItem> GetPickingItems(string orderId)
        {
            var list = materialprocessitemRepository.FindAll(p => p.OrderId == orderId).ToList();
            return list;
        }

        [HttpPost]
        public JsonResult Picking(string Id, IList<MaterialProcessItem> detail)
        {
            var data = materialprocessRepository.Find(Id);
            data.OrderState = "Picking";
            materialprocessRepository.Save(data);

            // 先删除所有子表，再保持所有子表数据
            materialprocessitemRepository.DeleteAll(m => m.OrderId == data.Id);
            foreach (var item in detail)
            {
                item.State = "Picking";
                item.Date = data.ProcessDate;
                materialprocessitemRepository.Insert(item);

                storageService.StorageOut(item.RawMaterialId, item.PickWeight, "加工领料");
            }
            return Json(nbAjaxMessage.Successful);
        }
        #endregion

        #region 入库
        public ActionResult Storage(string Id)
        {
            var data = materialprocessRepository.Find(Id);
            if (data.OrderState != "Picking")
            {
                throw new Exception(string.Format("当前加工单（{0}）的状态不是领料，所以无法入库！", Id));
            }

            // 子表数据
            var items = GetStorageItems(Id);
            ViewBag.detail = items;

            return View(data);
        }

        public IList<MaterialProcessItem> GetStorageItems(string orderId)
        {
            var list = materialprocessitemRepository.FindAll(p => p.OrderId == orderId).ToList();
            return list;
        }

        [HttpPost]
        public JsonResult Storage(string Id, IList<MaterialProcessItem> detail)
        {
            var data = materialprocessRepository.Find(Id);
            data.OrderState = "Storage";

            decimal totalWeight = 0;
            // 先删除所有子表，再保持所有子表数据
            materialprocessitemRepository.DeleteAll(m => m.OrderId == data.Id);
            foreach (var item in detail)
            {
                item.State = "Storage";
                materialprocessitemRepository.Insert(item);

                // 计算总重量
                totalWeight += item.ProcessWeight;

                // 加工入库
                storageService.StorageIn(item.MaterialId, item.StorageWeight, "加工入库");
            }
            data.TotalWeight = totalWeight;
            materialprocessRepository.Save(data);
            return Json(nbAjaxMessage.Successful);
        }
        #endregion

        #region 加工计划
        public ActionResult Plan()
        {
            return View();
        }

        [HttpPost]
        public JsonResult PlanList(DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            Expression<Func<MaterialProcessPlanView, bool>> filter = null;
            if (date.HasValue)
                filter = m => m.Date == date;

            var pageData = materialProcessPlanViewRepository.GetPageable(pager, filter, where);
            var data = pager.ToGridData(pageData);
            return Json(data);
        }
        #endregion

        #region 打印加工单
        public FileResult Export(string Id)
        {
            var ds = new DataSet();
            var ids = Id.Split(',');
            var processes = materialprocessRepository.FindAll(p => ids.Contains(p.Id)).ToList();
            var materials = materialprocessitemRepository.FindAll(item => ids.Contains(item.OrderId)).ToList();
            ds.AddNestedList(processes, materials, p => p.Id, c => c.OrderId, "Process", "Materials");

            var data = wordExporter.ExportPDF(ds, Server.MapPath("~/Upload/Templates/Process.doc"), e =>
            {
                if (e.FieldName == "Category")
                    e.Text = enumService.GetEnumText("MaterialCategory", e.FieldValue.ToString());
            });

            return File(data, "Application/pdf");
        }
        #endregion

        #region 加工明细
        public ActionResult Detail()
        {
            return View();
        }

        [HttpPost]
        public JsonResult DetailList(string state, DateTime? date, nbPageInfo pager, nbSearchCondition where)
        {
            Expression<Func<MaterialProcessItem, bool>> filter = null;
            if (date.HasValue)
            {
                filter = filter.And(p => p.Date == date);
            }
            if (!string.IsNullOrEmpty(state))
            {
                filter = filter.And(p => p.State == state);
            }

            var pageData = materialprocessitemRepository.GetPageable(pager, filter, where);
            var data = pager.ToGridData(pageData);
            return Json(data);
        }
        #endregion
    }
}
